/*
 *
 *  * Copyright (c) 2016. For Intelligent Group.
 *
 */

package com.intelligent.ispc.client.core.view.analysis;

import com.google.common.collect.Lists;
import com.intelligent.ispc.client.event.SearchParamsChangeEvent;
import com.intelligent.ispc.client.utils.EventBusUtils;
import com.intelligent.ispc.client.utils.GBC;
import com.intelligent.ispc.common.utils.StringUtils;
import com.intelligent.ispc.constant.AppConstant;
import com.intelligent.ispc.core.dto.DynSearchFieldDto;
import com.intelligent.ispc.foundation.parser.ParserToken;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Peter on 2016/7/7.
 */
public class AnalysisSearchPanel extends JPanel {

    private Map<String, Integer> componentMap;
    private List<DynSearchFieldDto> baseFields;
    private List<DynSearchFieldDto> cacheFields;
    private String moduleKey;

    private static int baseSearch = 0;
    private static int advanceSearch = 1;
    private int activity = advanceSearch;

    /**
     * Constructor
     *
     * @param module ehich panel
     */
    public AnalysisSearchPanel(String module) {
        this.moduleKey = module;
        initComponent();
    }

    private void initComponent() {
        componentMap = new HashMap<>();

        basePanel = new JPanel();
        advancePanel = new JPanel();
        panel = new JPanel();
        jScrollPane = new JScrollPane();
        toggleButton = new JButton("Advance");

        basePanel.setBorder(BorderFactory.createTitledBorder("Base Filter"));
        basePanel.setLayout(new GridBagLayout());


        advancePanel.setBorder(BorderFactory.createTitledBorder("Advance Filter"));
        advancePanel.setLayout(new GridBagLayout());
        initAdvancePanel();

        JPanel btnPanel = new JPanel();
        btnPanel.setLayout(new GridBagLayout());
        btnPanel.add(toggleButton, new GBC(0, 0).setFill(GBC.BOTH).setWeight(50, 100));


        panel.setLayout(new GridBagLayout());
        panel.setBorder(BorderFactory.createEmptyBorder());

        panel.add(basePanel, new GBC(0, 0).setFill(GBC.BOTH));
        panel.add(advancePanel, new GBC(0, 1).setFill(GBC.BOTH));
        panel.add(btnPanel, new GBC(0, 2).setFill(GBC.BOTH));
        panel.add(new JPanel(), new GBC(0, 3).setFill(GBC.BOTH).setWeight(100, 100));

        toggleButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                toggleButtonActionPerformed(e);
            }
        });

        jScrollPane.setViewportView(panel);
        jScrollPane.setBorder(BorderFactory.createEmptyBorder());
        this.setLayout(new GridBagLayout());
        this.setBorder(BorderFactory.createEmptyBorder());
        this.add(jScrollPane, new GBC(0, 0).setFill(GBC.BOTH).setWeight(100, 100));
        changeSearchModal();
    }

    /**
     * Set base fields
     *
     * @param params search conditions list
     */
    public void setBaseFields(List<DynSearchFieldDto> params) {
        this.baseFields = params;
        initBasePanel();
    }

    private void initBasePanel() {
        if (baseFields != null) {
            basePanel.removeAll();
            for (int i = 0; i < baseFields.size(); i++) {
                String name = baseFields.get(i).getName();
                Boolean isLike = baseFields.get(i).isLike();
                basePanel.add(buildInputComponent(name, isLike), new GBC(0, i).setFill(GBC.HORIZONTAL).setAnchor(GBC.NORTHWEST));
            }
            basePanel.add(new JPanel(), new GBC(0, baseFields.size()).setFill(GBC.BOTH).setWeight(1, 1).setAnchor(GBC.NORTHWEST));
            this.updateUI();
        }
    }

    private void initAdvancePanel() {
        JTextField textField = new JTextField();
        advancePanel.add(textField, new GBC(0, 0).setFill(GBC.HORIZONTAL).setWeight(100, 0));
    }

    private JPanel buildInputComponent(String name, Boolean isExactly) {
        JPanel jpanel = new JPanel();
        jpanel.setName(name);
        final int textFieldSize = 10;
        JTextField textField = new JTextField(textFieldSize);
        JCheckBox isExactlyBox = new JCheckBox(AppConstant.SPC_SEARCH_CHECKBOX_NAME);
        isExactlyBox.setSelected(isExactly);
        JLabel label = new JLabel(name);
        final Dimension labelSize = new Dimension(80, 10);
        label.setPreferredSize(labelSize);

        jpanel.setLayout(new GridBagLayout());
        jpanel.add(label, new GBC(0, 0, 2, 1).setFill(GBC.HORIZONTAL).setInsets(3, 0, 1, 0));
        jpanel.add(textField, new GBC(0, 1).setFill(GBC.HORIZONTAL).setWeight(100, 0));
        jpanel.add(isExactlyBox, new GBC(1, 1).setFill(GBC.HORIZONTAL).setWeight(10, 0).setInsets(0, 2, 0, 0));

        textField.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                update(e);
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                update(e);
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                update(e);
            }

            private void update(DocumentEvent e) {
                EventBusUtils.post(new SearchParamsChangeEvent(moduleKey, SearchParamsChangeEvent.TYPE_CONDITION, isValidData()));
            }
        });
        componentMap.put(name, AppConstant.FIELD_TYPE_INPUT);
        return jpanel;
    }

    /**
     * Toggle the button response event
     *
     * @param e ActionEvent
     */
    public void toggleButtonActionPerformed(ActionEvent e) {
        changeSearchModal();
    }

    /**
     * Clean panel
     */
    public void cleanPanel() {
        panel.removeAll();
    }

    /**
     * Clean base fields
     */
    public void cleanBaseFields() {
        initBasePanel();
    }

    /**
     * Clean advance fields
     */
    public void cleanAdvanceFields() {
        ((JTextField) advancePanel.getComponent(0)).setText("");
    }

    private void changeSearchModal() {
        if (activity == advanceSearch) {
            basePanel.setVisible(true);
            advancePanel.setVisible(false);
            toggleButton.setText("Advance Filter");
            activity = baseSearch;
        } else if (activity == baseSearch) {
            basePanel.setVisible(false);
            advancePanel.setVisible(true);
            toggleButton.setText("Base Filter");
            activity = advanceSearch;
        }
    }

    /**
     * Get search params
     *
     * @return search conditions list
     */
    public List<DynSearchFieldDto> getSearchParams() {
        List<DynSearchFieldDto> searchParams = Lists.newArrayList();

        if (activity == advanceSearch) {
            JTextField advanceText = (JTextField) advancePanel.getComponent(0);
            if (StringUtils.isNotBlank(advanceText.getText())) {
                DynSearchFieldDto dto = new DynSearchFieldDto();
                dto.setAdvance(true);
                dto.setValue(advanceText.getText());
                searchParams.add(dto);
            }
        } else if (activity == baseSearch) {
            for (int i = 0; i < basePanel.getComponentCount() - 1; i++) {
                if (basePanel.getComponent(i) instanceof JPanel) {
                    JPanel component = (JPanel) basePanel.getComponent(i);
                    if (component.getName() != null) {
                        setSearchParams(component, searchParams);
                    }
                } else {
                    JScrollPane component = (JScrollPane) basePanel.getComponent(i);
                    if (component.getName() != null) {
                        setSearchParams(component, searchParams);
                    }
                }
            }
        } else {
            return null;
        }

        return searchParams;
    }

    public void setCacheData(List<DynSearchFieldDto> cacheDto) {
        this.cacheFields = cacheDto;
    }

    /**
     * Judge the data is valid or not
     *
     * @return true when is valid
     */
    public boolean isValidData() {
        List<DynSearchFieldDto> dto = getSearchParams();
        boolean result = true;
        if (cacheFields == null) {
            return true;
        }
        if (cacheFields.size() != dto.size()) {
            return false;
        }
        List<String> selectedName = Lists.newArrayList();
        List<String> cacheName = Lists.newArrayList();

        for (DynSearchFieldDto d : dto) {
            selectedName.add(d.getName());
        }

        for (DynSearchFieldDto cd : cacheFields) {
            cacheName.add(cd.getName());
        }

        for (String s : selectedName) {
            if (!cacheName.contains(s)) {
                return false;
            }
        }

        for (DynSearchFieldDto d : dto) {
            for (DynSearchFieldDto cd : cacheFields) {
                if (d.getName().equals(cd.getName())) {
                    if (d.getValue().equals(cd.getValue())) {
                        continue;
                    } else {
                        return false;
                    }
                }
            }
        }
        return result;
    }


    private void setSearchParams(JComponent component, List<DynSearchFieldDto> searchParams) {
        String name = component.getName();
        DynSearchFieldDto searchParam = new DynSearchFieldDto();
        if (componentMap.get(name) == AppConstant.FIELD_TYPE_INPUT) {
            JTextField textField = (JTextField) component.getComponent(1);
            JCheckBox box = (JCheckBox) component.getComponent(2);
            if (!StringUtils.isBlank(textField.getText())) {
                searchParam.setName(name);
                if (box.isSelected()) {
                    searchParam.setToken(ParserToken.LIKE.getCode());
                } else {
                    searchParam.setToken(ParserToken.EQ.getCode());
                }
                searchParam.setLike(box.isSelected());
                searchParam.setValue(textField.getText());
                searchParams.add(searchParam);
            }
        }
    }

    private JScrollPane jScrollPane;
    private JButton toggleButton;
    private JPanel basePanel;
    private JPanel advancePanel;
    private JPanel panel;

}
